<!-- author: xuett -->
<!-- date: 2025-06-09 14:48:48 -->
<!-- description: 机房 -->
<template>
  <div>
    <div ref="container" class="container" @click="selectCabinet">
      <div class="plane" :style="{ left: planePos.left, top: planePos.top, display: planePos.hasDisplay ? 'block' : 'none' }">
        <div>机柜名称：{{ curCabinetInfo.name }}</div>
        <div>机柜编号：{{ curCabinetInfo.code }}</div>
        <el-button type="primary" @click="goRackDetail(curCabinetInfo)">查看详情</el-button>
      </div>
    </div>
  </div>
</template>

<script setup>
import * as THREE from "three";
import Viewer from "@/hooks/viewer.js";
import postprocessing from "@/hooks/postprocessing.js";
import createRoom from "@/utils/createRoom";
import { createCabinets } from "@/utils/createCabinets";

const $router = useRouter();

let viewerIns = null,
  postprocessingIns = null;

//鼠标划入的机柜
var curCabinet = null;

const container = ref(null);
const state = reactive({
  showPostProcessing: true,
  roomSize: { width: 10, height: 7 },
  // 信息框位置
  planePos: {
    hasDisplay: false,
    left: 0,
    top: 0
  },
  //选中机柜信息
  curCabinetInfo: {}
});
const { planePos, curCabinetInfo } = toRefs(state);

onMounted(() => {
  init();
});

var animationId;
onUnmounted(() => {
  // 清理资源
  cancelAnimationFrame(animationId);
  if (viewerIns) {
    viewerIns.dispose();
  }
});

const init = async () => {
  viewerIns = new Viewer(container);
  // 创建后处理效果
  if (state.showPostProcessing) {
    postprocessingIns = new postprocessing(viewerIns, container);
  }

  const room = createRoom(state.roomSize);
  viewerIns.scene.add(room);
  let arr = [
    [1, 1],
    [2, 1],
    [3, 1],
    [4, 1],
    [3, 3],
    [8, 6]
  ];
  const cabinets = await createCabinets(state.roomSize, arr);
  viewerIns.scene.add(...cabinets);
  viewerIns.setRaycasterObjects(cabinets);

  // 处理窗口大小调整
  window.addEventListener("resize", () => onWindowResize());
  viewerIns.renderer.autoClear = false;
  animate();
};

// 窗口大小调整处理函数
const onWindowResize = () => {
  const width = container.value.clientWidth;
  const height = container.value.clientHeight;
  viewerIns.resize(width, height);
  postprocessingIns.resize(width, height);
};

// 动画循环
const animate = () => {
  // 使用后处理合成器渲染场景
  // if (state.showPostProcessing) {
  //   postprocessingIns.render();
  //   viewerIns.controls.update();
  // } else {
  //   //不使用后处理，直接渲染场景
  //   viewerIns.render();
  // }

  viewerIns.renderer.clear();
  viewerIns.camera.layers.set(1);
  postprocessingIns.composer.render();

  viewerIns.renderer.clearDepth();
  viewerIns.camera.layers.set(0);
  viewerIns.render();

  animationId = requestAnimationFrame(animate);
};

const selectCabinet = (mouseEvent) => {
  let intersectObj = viewerIns.getRaycasterIntersectObjects(mouseEvent);
  /*
        若当前所选对象不为空：
          将模型高亮。
          触发鼠标在机柜上移动的事件。
          若当前所选对象不等于上一次所选对象：
            更新curCabinet。
            触发鼠标划入机柜事件。
        否则若上一次所选对象存在：
          置空curCabinet。
          触发鼠标划出机柜事件。
      */
  if (intersectObj) {
    // 切换该对象的高亮状态
    if (state.showPostProcessing) {
      postprocessingIns.toggleOutline(intersectObj);
    }

    // onMouseMoveCabinet(x, y);
    if (intersectObj !== curCabinet) {
      selectObject(intersectObj, mouseEvent);
      // onMouseOverCabinet(intersectObj);
    }
  } else if (curCabinet) {
    // onMouseOutCabinet();
    deselectObject();
  }
};

const selectObject = (object, mouseEvent) => {
  // 取消之前选中的对象
  deselectObject();
  curCabinet = object;

  //显示信息窗
  state.curCabinetInfo = object.userData;
  state.planePos.left = mouseEvent.clientX + "px";
  state.planePos.top = mouseEvent.clientY + "px";
  state.planePos.hasDisplay = Object.keys(object.userData).length ? true : false;

  // 创建线框材质
  const wireframeMaterial = new THREE.LineBasicMaterial({
    color: 0xffffff
  });
  // 创建线框几何体
  const edges = new THREE.EdgesGeometry(object.geometry);
  const wireframe = new THREE.LineSegments(edges, wireframeMaterial);
  // wireframe.layers.set(1);
  // 将线框添加到选中模型
  curCabinet.add(wireframe);
};

const deselectObject = () => {
  state.planePos.hasDisplay = false;
  if (curCabinet) {
    let index = curCabinet.children.findIndex((item) => item.type == "LineSegments");
    if (index > -1) {
      curCabinet.children[index].material.dispose();
      curCabinet.remove(curCabinet.children[index]);
    }
    curCabinet = null;
  }
};

//鼠标划入机柜事件，参数为机柜对象
const onMouseOverCabinet = (cabinet) => {
  state.curCabinetInfo = {
    name: cabinet.userData.name
  };
  state.planePos.hasDisplay = true;
};
//鼠标在机柜上移动的事件，参数为鼠标在canvas画布上的坐标位
const onMouseMoveCabinet = (x, y) => {
  // console.log(x, y);
  state.planePos.left = x + "px";
  state.planePos.top = y + "px";
};
//鼠标划出机柜的事件
const onMouseOutCabinet = () => {
  state.planePos.hasDisplay = false;
};

//机柜详情
const goRackDetail = () => {
  $router.push("/iim-rack");
};
</script>

<style>
.container {
  position: absolute;
  width: 100%;
  height: 100%;
  .plane {
    position: absolute;
    top: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.6);
    padding: 0 18px;
    transform: translate(12px, -100%);
    display: none;
    color: #fff;
    font-size: 16px;
    font-weight: normal;
  }
}
</style>
